package com.example.makerspace.handler;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.makerspace.cache.TreeFileInfo;
import com.example.makerspace.cache.TreeFileItem;
import com.example.makerspace.dao.*;
import com.example.makerspace.domain.*;
import com.example.makerspace.dto.Result;
import com.example.makerspace.utils.DateUtils;
import com.example.makerspace.utils.JwtUtils;
import com.example.makerspace.utils.RedisUtils;
import com.example.makerspace.vo.ProductRecommendationVO;
import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.RemoteAddCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.Repository;
import org.gitlab4j.api.models.TreeItem;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.example.makerspace.utils.FileUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.example.makerspace.cache.GitLabConstants.*;
import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;

@Component("taskJobHandler")
public class TaskJobHandler {
    public final static double PRAISE =  0.5;
    public final static Integer COLLECTION = 1;
    public final static double SHARE = 0.3;
    public final static double STAY = 0.1;
    public final static double IndustriesInterest = 0.1;
    public final static double ADDRESS = 0.3;

    public  static  String errorPath="";
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private SingInDataDAO singInDataDAO;

    @Resource
    private DemandDAO demandDAO;

    @Resource
    private UserDAO userDAO;

    @Resource
    private  ExpertTaskDAO expertTaskDAO;

    @Resource
    private PersonalRecommendationsDAO personalRecommendationsDAO;

    @Resource
    private CustomerNumberDAO customerNumberDAO;

    @Resource
    private  AgencyProductRelationshipsDAO  agencyProductRelationshipsDAO;

    @Resource
    private TaskOutComeReviewDAO taskOutComeReviewDAO;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private  UserProjectDAO userProjectDAO;


    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
    public void updateSort() {
        List<PersonalRecommendationsDO> personalRecommendationsDOS = personalRecommendationsDAO.selectAll();
        for(PersonalRecommendationsDO personalRecommendationsDO:personalRecommendationsDOS){
            personalRecommendationsDO.setWeight(personalRecommendationsDO.getPerWeight());
            personalRecommendationsDAO.updateById(personalRecommendationsDO);
        }
        System.out.println("更新评分");
        System.out.println(new Date());
    }

    @Scheduled(cron="0/5 * *  * * ? ")
    public void initProduct() {

        List<DemandDO> demandDOS = demandDAO.selectAll();
        List<DemandDO> collect = demandDOS.stream().filter(item -> item.getIsShow().equals(1)).collect(Collectors.toList());
        List<UserDO> userDOS = userDAO.selectAll();
        for(int i=0;i<collect.size();i++){
            for(int j=0;j<userDOS.size();j++){
            PersonalRecommendationsDO personalRecommendationsDO1 = personalRecommendationsDAO.selectByProductId(userDOS.get(j).getUsername(), collect.get(i).getId());
            if(personalRecommendationsDO1!=null){
                continue;
            }
            synchronized (PersonalRecommendationsDO.class){
                double result=0;
                PersonalRecommendationsDO personalRecommendationsDO = new PersonalRecommendationsDO();
                personalRecommendationsDO.setStay(0);
                personalRecommendationsDO.setUsername(userDOS.get(j).getUsername());
                personalRecommendationsDO.setProductId(collect.get(i).getId());
                UserDO userDO = userDAO.selectByUsername(userDOS.get(j).getUsername());
                if(userDO.getMapAddress()!=null){
                    if(userDO.getMapAddress().equals(collect.get(i).getCompanyAddress())){
                        result=result+ADDRESS;
                    }
                }
                List<String> praiseUser =collect.get(i).getPraiseUser();
                boolean contains = praiseUser.contains(userDOS.get(j).getUsername());
                if(contains){
                    result=result+PRAISE;
                }
                List<String> collectionUser = collect.get(i).getCollectionUser();
                boolean contains1 = collectionUser.contains(userDOS.get(j).getUsername());
                if(contains1){
                    result=result+COLLECTION;
                }
                List<String> shareUser = collect.get(i).getShareUser();
                boolean contains2 = shareUser.contains(userDOS.get(j).getUsername());
                if(contains2){
                    result=result+SHARE;
                }
                personalRecommendationsDO.setWeight(result);
                personalRecommendationsDO.setPerWeight(result);
                personalRecommendationsDAO.insert(personalRecommendationsDO);
            }
        }
      }
    }
//    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
//    public void insertWebSocket() {
//        LocalDate localDate = LocalDate.now();
//        int flash=0;
//        List<CustomerNumberDO> customerNumberDOS = customerNumberDAO.selectAll();
//        for(int i=0;i<customerNumberDOS.size();i++){
//            Date createTime = customerNumberDOS.get(i).getCreateTime();
//            LocalDate localDate1= createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
//            if(localDate.isEqual(localDate1)){
//                flash=1;
//            }
//        }
//        if(flash==1){
//            return;
//        }else {
//            CustomerNumberDO customerNumberDO = new CustomerNumberDO();
//            customerNumberDO.setReplyNumber(0);
//            customerNumberDO.setUserNumber(0);
//            customerNumberDAO.insert(customerNumberDO);
//            System.out.println("又插入了");
//        }
//    }


    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
    public void ifHasExpired() {
        List<AgencyProductRelationshipsDO> agencyProductRelationshipsDOS = agencyProductRelationshipsDAO.selectAll();
        for(int i=0;i<agencyProductRelationshipsDOS.size();i++){
            List<String> deadline = agencyProductRelationshipsDOS.get(i).getDeadline();
            if(!CollectionUtils.isEmpty(deadline)){
                String Deadline = deadline.get(deadline.size() - 1);
                LocalDate localDate = LocalDate.now();
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate date = LocalDate.parse(Deadline, fmt);
                if(localDate.isEqual(date)){
                    String entName = agencyProductRelationshipsDOS.get(i).getEntName();
                    List<AgencyProductRelationshipsDO> agencyProductRelationshipsDOList = agencyProductRelationshipsDAO.selectByEntName(entName);
                    for(int j=0;j<agencyProductRelationshipsDOList.size();j++){
                        Integer productId = agencyProductRelationshipsDOS.get(i).getProductId();
                        if(productId!=null){
                            DemandDO demandDO = demandDAO.selectById(productId);
                            if(demandDO.getIsShow().equals(0)||demandDO.getIsShow().equals(-1)){
                                demandDAO.deleteById(productId);
                            }
                        }
                    }
                    agencyProductRelationshipsDAO.deleteByEntName(entName);
                }
            }

        }
    }
//    @Scheduled(cron="0 0 0 0/6 * ?  ")   //每7天执行一次
//    public void flushedWeekTime() {
//        List<UserProjectDO> userProjectDOS = userProjectDAO.selectAll();
//        for(int i=0;i<userProjectDOS.size();i++){
//            userProjectDOS.get(i).setWeekViewNumber(0);
//            userProjectDAO.updateById(userProjectDOS.get(i));
//        }
//    }
//    @Scheduled(cron="0 0 0 0/29 * ? ")   //每30天执行一次
//    public void flushedMonthTime() {
//        List<UserProjectDO> userProjectDOS = userProjectDAO.selectAll();
//        for(int i=0;i<userProjectDOS.size();i++){
//            userProjectDOS.get(i).setMonthViewNumber(0);
//            userProjectDAO.updateById(userProjectDOS.get(i));
//        }
//    }


    //更新主文件的缓存 /--根路径下的缓存
    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
    public void isHaveDate() throws GitLabApiException {
        GitLabApi gitlabapi = null;
        List<TreeItem> tree = null;
        List<Commit> commits;
        try {
            gitlabapi = GitLabApi.oauth2Login(
                    GITLAB_REMOTE_USERNAME,
                    REMOTE_USERNAME,
                    GITLAB_REMOTE_PWD);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<UserProjectDO> userProjectDOS = userProjectDAO.selectAll();
        List<Integer> projectIds = userProjectDOS.stream().map(item -> item.getProjectId()).collect(Collectors.toList());
        List<String> defaultBranchList = userProjectDOS.stream().map(item -> item.getDefaultBranch()).collect(Collectors.toList());
        for (int i = 0; i < projectIds.size(); i++) {
            List<TreeFileItem> itemList = new ArrayList<>();
            tree = gitlabapi.getRepositoryApi().getTree(projectIds.get(i), "/", defaultBranchList.get(i), true);
            String key = projectIds.get(i) + "-/-" + defaultBranchList.get(i);
            for (int j = 0; j < tree.size(); j++) {
                TreeFileItem treeFileItem = new TreeFileItem();
                commits = gitlabapi.getCommitsApi().getCommits(projectIds.get(i), defaultBranchList.get(i), tree.get(j).getPath());
                BeanUtils.copyProperties(tree.get(j), treeFileItem);
                if (!org.springframework.util.CollectionUtils.isEmpty(commits)) {
                    treeFileItem.setMessage(commits.get(0).getMessage());
                    Date committedDate = commits.get(0).getCommittedDate();
                    treeFileItem.setCommittedDate(DateUtils.format(committedDate, DateUtils.YYYY_MM_DD));
                }
                itemList.add(treeFileItem);
            }
            String result = redisUtils.get(key);

            if (StringUtils.isNotEmpty(result)) {
                String jsonString = JSON.toJSONString(itemList);
                if (!result.equals(jsonString)) {
                    redisUtils.set(key, jsonString);
                }
            } else {
                String jsonString = JSON.toJSONString(itemList);
                redisUtils.set(key, jsonString);
            }
        }
    }





//    @Scheduled(cron="0/1 * *  * * ? ")   //每5秒执行一次
//    public void isFileDate() throws GitLabApiException {
//        GitLabApi gitlabapi = null;
//        List<TreeItem> tree = null;
//        List<TreeItem> treePath = null;
//        List<Commit> commits;
//        try {
//            gitlabapi = GitLabApi.oauth2Login(
//                    GITLAB_REMOTE_USERNAME,
//                    REMOTE_USERNAME,
//                    GITLAB_REMOTE_PWD);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        List<UserProjectDO> userProjectDOS = userProjectDAO.selectAll();
//        List<Integer> projectIds = userProjectDOS.stream().map(item -> item.getProjectId()).collect(Collectors.toList());
//        List<String> defaultBranchList = userProjectDOS.stream().map(item -> item.getDefaultBranch()).collect(Collectors.toList());
//        for (int i = 0; i < projectIds.size(); i++) {
//            tree = gitlabapi.getRepositoryApi().getTree(projectIds.get(i), "/", defaultBranchList.get(i), true);
//            for (int j = 0; j < tree.size(); j++) {
//                String key = projectIds.get(i) + "-" +tree.get(j).getPath() + "-" + defaultBranchList.get(i);
//                List<TreeFileItem> itemList = new ArrayList<>();
//                treePath = gitlabapi.getRepositoryApi().getTree(projectIds.get(i), tree.get(j).getPath(), defaultBranchList.get(i), true);
//                for(int z=0;z<treePath.size();z++){
//                    TreeFileItem treeFileItem = new TreeFileItem();
//                    commits = gitlabapi.getCommitsApi().getCommits(projectIds.get(i), defaultBranchList.get(i),treePath.get(z).getPath());
//                    BeanUtils.copyProperties(treePath.get(z), treeFileItem);
//                    if (!org.springframework.util.CollectionUtils.isEmpty(commits)) {
//                        treeFileItem.setMessage(commits.get(0).getMessage());
//                        Date committedDate = commits.get(0).getCommittedDate();
//                        treeFileItem.setCommittedDate(DateUtils.format(committedDate, DateUtils.YYYY_MM_DD));
//                    }
//                    itemList.add(treeFileItem);
//                }
//                String result = redisUtils.get(key);
//
//                if (StringUtils.isNotEmpty(result)) {
//                    String jsonString = JSON.toJSONString(itemList);
//                    if (!result.equals(jsonString)) {
//                        redisUtils.set(key, jsonString);
//                    }
//                } else {
//                    String jsonString = JSON.toJSONString(itemList);
//                    redisUtils.set(key, jsonString);
//                }
//            }
//        }
//    }
    /**
     * 删除单个文件
     * @param   sPath    被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public boolean deleteFile3(String sPath) {
        Boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
    /**
     * 删除目录（文件夹）以及目录下的文件
     * @param   sPath 被删除目录的文件路径
     * @return  目录删除成功返回true，否则返回false
     */
    public boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        Boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile3(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    public static double getFolderSizeInMB(File folder) {
        long sizeInBytes = 0;
        File[] files = folder.listFiles();
        if (files!= null) {
            for (File file : files) {
                if (file.isFile()) {
                    sizeInBytes += file.length();
                } else if (file.isDirectory()) {
                    sizeInBytes += getFolderSizeInMB(file);
                }
            }
        }
        double sizeInMB = sizeInBytes / (1024.0);
        return sizeInMB;
    }

    @Scheduled(cron="0/5 * *  * * ? ")
    public void download() {
        String desktopPath = "/home/ubuntu/java_project/static/";
        String localPath = null;
        Repository localRepo;
        Git git;
        List<UserProjectDO> userProjectDOS = userProjectDAO.selectAll();
        List<String> projectLinks = userProjectDOS.stream().map(item -> item.getProjectLink()).collect(Collectors.toList());
        List<String> projectNames = userProjectDOS.stream().map(item -> item.getProjectName()).collect(Collectors.toList());
        List<String> DefaultBranchList = userProjectDOS.stream().map(item -> item.getDefaultBranch()).collect(Collectors.toList());
        //认证凭据
        UsernamePasswordCredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("root","Ls422327276");
        try {
        for(int i=0;i<projectLinks.size();i++){
            localPath = desktopPath+File.separator+projectNames.get(i);
            if(localPath.equals(errorPath)){
                continue;
            }
            File folder = new File(localPath);
            double sizeInMB = getFolderSizeInMB(folder);
            BigDecimal bd = new BigDecimal(sizeInMB);
            bd = bd.setScale(2, RoundingMode.HALF_UP);
            userProjectDOS.get(i).setProjectSize(bd+"kb");
            userProjectDAO.updateById(userProjectDOS.get(i));
            FileRepository FileRepository = new FileRepository(localPath);
            git = new Git(FileRepository);
            File localPathFile = new File(localPath);
            if (!localPathFile.exists()) {
                gitClone(projectLinks.get(i),  DefaultBranchList.get(i), localPath, credentialsProvider);
            }else {
                gitPull(localPath,projectLinks.get(i),credentialsProvider);
            }
        }
        } catch (Exception e) {
            System.out.println(localPath);
            log.println(e.getMessage());
            e.printStackTrace();
            errorPath=localPath;

        }
    }
    /**
     * 如果没有该代码目录,执行git clone
     */
    private void gitClone(String gitUrl, String branch, String localPath,UsernamePasswordCredentialsProvider credentialsProvider) throws Exception {
        Git.cloneRepository().setURI(gitUrl).setBranch(branch)
                .setDirectory(new File(localPath)).setCredentialsProvider(credentialsProvider).call();
    }
    private  void  gitPull(String localAddress,String gitLink,UsernamePasswordCredentialsProvider credentialsProvider) throws IOException, URISyntaxException, GitAPIException {
        Git git=null;
        git = Git.open(new File(localAddress));

        RemoteAddCommand remoteAddCommand = git.remoteAdd();
        remoteAddCommand.setName("origin");
        remoteAddCommand.setUri(new URIish(gitLink));
        remoteAddCommand.call();
        PullCommand pull = git.pull();
        pull.setCredentialsProvider(credentialsProvider);
        // 添加所有更改
        pull.setRemoteBranchName("master");
        pull.call();
    }

}
